package ar.camera.glsurfaceview.extend;

import android.content.Context;
import android.graphics.PointF;
import android.util.FloatMath;
import android.view.MotionEvent;
import ar.activity.ARCameraActivity;
import ar.camera.glsurfaceview.base.BaseGLSurfaceView;
import ar.camera.pojo.GLPoint;
import ar.camera.renderer.base.BaseRenderer;
import ar.camera.renderer.extend.LocationIconRenderer;
import ar.globals.Globals;
import ar.utils.GLIconUtils;

public class LocationIconSurfaceView extends BaseGLSurfaceView {

	private BaseRenderer mPlaneRenderer;
	private BaseRenderer mCompassRenderer;

	public void setmCompassRenderer(BaseRenderer mCompassRenderer) {
		this.mCompassRenderer = mCompassRenderer;
	}

	public void setmPlaneRenderer(BaseRenderer mPlaneRenderer) {
		this.mPlaneRenderer = mPlaneRenderer;
	}

	static final int NONE = 0;
	static final int DRAG = 1;
	static final int ZOOM = 2;
	private int mode = NONE;
	private PointF mStartPoint;
	private PointF mMidPoint = new PointF();
	private float mOldDist = 0;
	private GLPoint savedEye;
	private GLPoint savedCam;	

	public LocationIconSurfaceView(Context context, ARCameraActivity ac) {
		super(context);

		GLPoint cam = new GLPoint(0f, 0f, -1f);
		GLPoint eye = new GLPoint(0f, 0f, 0f);
		mRenderer = new LocationIconRenderer(context, eye, cam, ac);
		setRenderer(mRenderer);

		savedEye = mRenderer.getEye();
		savedCam = mRenderer.getCam();
	}

	public int getMode() {
		return mode;
	}

	public void setMode(int mode) {
		this.mode = mode;
	}

	public int getNone() {
		return NONE;
	}

	public void updateLocationIcons() {

	}	

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		GLPoint cam = mRenderer.getCam();
		GLPoint camZoom = new GLPoint(savedCam.x, savedCam.y, savedCam.z);
		GLPoint eye = new GLPoint(savedEye.x, savedEye.y, savedEye.z);
		float angle = 0;
		switch (event.getActionMasked()) {
		case MotionEvent.ACTION_DOWN:
			mStartPoint = new PointF(event.getX(), event.getY());
			mode = DRAG;
			break;
		case MotionEvent.ACTION_POINTER_DOWN:
			mOldDist = spacing(event);
			if (mOldDist > 10f) {
				midPoint(mMidPoint, event);
				mode = ZOOM;
			}
			if (event.getPointerCount() >= 3) {
				mode = NONE;
				eye = new GLPoint(0f, 0f, 0f);
				cam = new GLPoint(0f, 0f, -1f);
				mPlaneRenderer.setCam(cam);
				mPlaneRenderer.setEye(eye);
				mRenderer.setEye(eye);
				mRenderer.setCam(cam);
				mRenderer.updateVertices(0f, null, null);

				((LocationIconRenderer) mRenderer).setUpdateSensor(true);
			}
			break;
		case MotionEvent.ACTION_UP:
			savedEye = mRenderer.getEye();
			savedCam = mRenderer.getCam();
			mode = NONE;
			break;
		case MotionEvent.ACTION_POINTER_UP:
			mode = NONE;
			break;
		case MotionEvent.ACTION_MOVE:
			if (mode == DRAG) {
				angle = (float) ((event.getX() - mStartPoint.x) * 90 / 800
						* Math.PI / 180);

				cam = GLIconUtils.rotateY(cam, eye, angle);
				float azimut = GLIconUtils.calculateAngleBetweenOzAndEyeCam(
						eye, cam);

				mRenderer.setCam(cam);
				mRenderer.updateVertices((float) (azimut * 180 / Math.PI),
						null, null);
				mStartPoint = new PointF(event.getX(), event.getY());

				GLPoint planeCam = new GLPoint(cam.x * 10, cam.y, cam.z * 10);
				GLPoint planeEye = new GLPoint(eye.x * 10, eye.y, eye.z * 10);
				mPlaneRenderer.setCam(planeCam);
				mPlaneRenderer.setEye(planeEye);
				// mPlaneRenderer.setCam(cam);
				// mPlaneRenderer.setEye(eye);
				GLPoint miniMapEye = new GLPoint(eye.x * Globals.RADIUS
						/ Globals.MAX_RADIUS, eye.y, eye.z * Globals.RADIUS
						/ Globals.MAX_RADIUS);
				mCompassRenderer.updateVertices(
						180f - (float) (azimut * 180 / Math.PI), miniMapEye,
						cam);
				// mCompassRenderer.updateVertices(
				// 180f - (float) (azimut * 180 / Math.PI), eye, cam);
			}
			if (mode == ZOOM) {
				float a = (eye.x - camZoom.x) / (eye.z - camZoom.z);
				float b = (eye.x * camZoom.z - camZoom.x * eye.z)
						/ (camZoom.z - eye.z);
				float newDist = spacing(event);
				float scale = newDist / mOldDist;
				float signScale = (scale - 1) / Math.abs(scale - 1);
				float signZ = (camZoom.z - eye.z) / Math.abs(camZoom.z - eye.z);
				if (scale < 1) {
					scale = 1 / scale;
				}
				eye.z += signScale * signZ * Math.abs(scale - 1) / (1.5f);
				camZoom.z += signScale * signZ * Math.abs(scale - 1) / (1.5f);				

				eye.x = eye.z * a + b;
				camZoom.x = camZoom.z * a + b;

				float azimut = GLIconUtils.calculateAngleBetweenOzAndEyeCam(
						eye, camZoom);
				mRenderer.setEye(eye);
				mRenderer.setCam(camZoom);
				mRenderer.updateVertices((float) (azimut * 180 / Math.PI),
						null, null);
				GLPoint planeCam = new GLPoint(camZoom.x * 10, camZoom.y,
						camZoom.z * 10);
				GLPoint planeEye = new GLPoint(eye.x * 10, eye.y, eye.z * 10);
				mPlaneRenderer.setCam(planeCam);
				mPlaneRenderer.setEye(planeEye);
				// mPlaneRenderer.setCam(camZoom);
				// mPlaneRenderer.setEye(eye);
				GLPoint miniMapEye = new GLPoint(eye.x * Globals.RADIUS
						/ Globals.MAX_RADIUS, eye.y, eye.z * Globals.RADIUS
						/ Globals.MAX_RADIUS);
				mCompassRenderer.updateVertices(
						180f - (float) (azimut * 180 / Math.PI), miniMapEye,
						camZoom);
				// mCompassRenderer.updateVertices(
				// 180f - (float) (azimut * 180 / Math.PI), eye, camZoom);
			}
			break;
		}
		return true;
	}

	private void midPoint(PointF point, MotionEvent event) {
		float x = event.getX(0) + event.getX(1);
		float y = event.getY(0) + event.getY(1);
		point.set(x / 2, y / 2);
	}

	private float spacing(MotionEvent event) {
		float x = event.getX(0) - event.getX(1);
		float y = event.getY(0) - event.getY(1);
		return FloatMath.sqrt(x * x + y * y);
	}

}
